package com.leyou.gateway.filter;


import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.CookieUtils;
import com.leyou.gateway.config.AllowPathProperties;
import com.leyou.gateway.config.JwtProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import java.util.List;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * 请求到达网关，验证用户是否登录
 */
@Slf4j
@Component
@EnableConfigurationProperties({JwtProperties.class, AllowPathProperties.class})
public class AuthFilter extends ZuulFilter {

    @Autowired
    private JwtProperties prop;

    @Autowired
    private AllowPathProperties allowProp;

    /**
     * 设置 自定义过滤器的 类型
     * 设置为 前置
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 设置 自定义过滤器的 执行顺序
     * @return
     */
    @Override
    public int filterOrder() {
        return FORM_BODY_WRAPPER_FILTER_ORDER -1 ;
    }

    /**
     * 是否执行当前的过滤器
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return !isAllowPath();
    }

    /**
     * 判断是否 白名单请求
     *
     * @return  true - 是白名单   false-不在白名单内
     */
    private boolean isAllowPath(){
//        获取当前的请求地址
        RequestContext ctx = RequestContext.getCurrentContext();
        //      从 zuul的上下文中获取request
        HttpServletRequest request = ctx.getRequest();
        // 获取当前资源路径
        String path = request.getRequestURI();
        //获取白名单 集合
        List<String> allowPaths = allowProp.getAllowPaths();
//        判断当前的地址是否在白名单内
        for (String allowPath : allowPaths) {
            if(path.startsWith(allowPath)){
                return true;
            }
        }
        return false;
    }
    /**
     * 过滤器的业务逻辑
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        //      从 zuul的上下文中获取request
        HttpServletRequest request = ctx.getRequest();
        // 获取当前资源路径
        String path = request.getRequestURI();
        String method = request.getMethod();
        try{
//        获取request中的token
            String token = CookieUtils.getCookieValue(request, prop.getUserToken().getCookieName());
//        使用 公钥解析token
            if(token==null){
                return null;
            }
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey(), UserInfo.class);
//        获取用户信息
            UserInfo userInfo = payload.getUserInfo();
//        判断用户的权限
            String role = userInfo.getRole();

            // TODO 判断权限
            log.info("【网关】用户{},角色{}。访问服务{} : {}，", userInfo.getUsername(), role, method, path);
        }catch (Exception e){
           /* e.printStackTrace();*/
            log.error("非法访问，未登录，地址：{}", request.getRemoteHost(), e );
            // TODO 判断权限
            log.info("【网关】访问服务{} : {}，", method, path);
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }
}
